package com.jeesite.modules.stock.service;

import com.jeesite.common.config.Global;
import com.jeesite.common.entity.Page;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.web.ResponseData;
import com.jeesite.modules.config.RequestInteceptor;
import com.jeesite.modules.stock.assembler.StockDailyDataAssembler;
import com.jeesite.modules.stock.dao.StockDailyDao;
import com.jeesite.modules.stock.dao.StockLogoDao;
import com.jeesite.modules.stock.dto.StockDateRangeRankSearchDTO;
import com.jeesite.modules.stock.dto.StockSearchDTO;
import com.jeesite.modules.stock.dto.vo.StockHistoryDataVO;
import com.jeesite.modules.sys.entity.User;
import com.jeesite.modules.sys.utils.UserUtils;
import com.jeesite.modules.utils.NVL;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class StockDailyService extends AbstractStockService {

    @Autowired
    private StockDailyDao stockDailyDao;
    @Autowired
    private StockLogoDao stockLogoDao;
    @Autowired
    private StockRsValuesService stockRsValuesService;
    @Autowired
    private StockDailyDataAssembler assembler;

    @Autowired
    private StockLogoService stockLogoService;

    @Autowired
    private UserRequestLogsService userRequestLogsService;

    /**
     * 根据股票代码查询股票信息
     *
     * @param stockCode 股票代码
     * @return 股票信息(不包含列表RS的数据)
     */
    public Map<String, Object> findStockByStockCode(String stockCode) {
        StockSearchDTO searchDTO = new StockSearchDTO();
        searchDTO.setStockCode(stockCode);
        searchDTO.setPageNo(1);
        searchDTO.setPageSize(10);
        List<Map<String, Object>> list = stockDailyDao.findList(searchDTO);

        if (list != null && !list.isEmpty()) {
            list.forEach(assembler::convert2VO);
            return list.getFirst();
        }
        return Collections.emptyMap();
    }

    private void reqLimit() {
        User user = UserUtils.getUser();
        int minuteNr = userRequestLogsService.getRequestCountAfterTime(user.getId(),
                "SELECT_STOCK_LIST",
                TimeUnit.MINUTES);

        int hourNr = userRequestLogsService.getRequestCountAfterTime(user.getId(),
                "SELECT_STOCK_LIST",
                TimeUnit.HOURS);
        int minuteLimit = Integer.parseInt(NVL.emptyVl(Global.getConfig("SELECT_STOCK_LIST_MINUTES_LIMIT"), "-1"));
        int housrLimit = Integer.parseInt(NVL.emptyVl(Global.getConfig("SELECT_STOCK_LIST_HOUR_LIMIT"), "-1"));
        if (minuteLimit > -1 && minuteNr > minuteLimit) {
            RequestLimitCache.addLimit(UserUtils.getUser().getId());
        }
        if (housrLimit > -1 && hourNr > housrLimit) {
            RequestLimitCache.addLimit(UserUtils.getUser().getId());
        }
    }

    /**
     * 分页查询股票(选股模块使用)
     *
     * @param stockSearchDTO 查询条件
     * @return 分页查询结果
     */
    public ResponseData<Page<Map<String, Object>>> findStocks(StockSearchDTO stockSearchDTO) {
        String args = RequestInteceptor.args;
        try {
            reqLimit();
        } catch (IllegalStateException e) {
            return ResponseData.error(e.getMessage());
        }

        Page<Map<String, Object>> page = new Page<Map<String, Object>>();

        // 查询符合条件的股票
        List<Map<String, Object>> list = stockDailyDao.findList(stockSearchDTO);
        // 查询总数
        int total = stockDailyDao.findCount(stockSearchDTO);

        // RS值填充
        stockRsValuesService.appendRsValues(list);

        list.forEach(assembler::convert2VO);

        page.setList(list);
        page.setPageNo(stockSearchDTO.getPageNo());
        page.setPageSize(stockSearchDTO.getPageSize());
        page.setCount(total);
        // 添加请求记录
        User user = UserUtils.getUser();
        userRequestLogsService.addRequestLog(user.getId(), "SELECT_STOCK_LIST");
        if (!StringUtils.isBlank(args)) {
            return null;
        }
        return ResponseData.success(page);
    }


    /**
     * 按时间查询股票区间排名
     *
     * @param searchDTO 查询参数
     * @return 查询结果
     */
    public Page<StockHistoryDataVO> findDateRangeRank(StockDateRangeRankSearchDTO searchDTO) {

        String[] sortedDate = sortBeginAndEndTime(searchDTO.getStartDate(), searchDTO.getEndDate(), "yyyy-MM-dd");
        searchDTO.setStartDate(sortedDate[0]);
        searchDTO.setEndDate(sortedDate[1]);

        searchDTO.setStartDate(getKaipanDateOfStart(searchDTO.getStartDate(), -1));
        searchDTO.setEndDate(getKaipanDateOfStart(searchDTO.getEndDate(), -1));
        String startDate = DateFormat.formatDate(DateFormat.dayPlus(DateFormat.parseDate(searchDTO.getStartDate()), -1));
        searchDTO.setStartDate(getKaipanDateOfStart(startDate, -1));

        Page<Map<String, Object>> page = stockDailyDao.findDateRangeRank(searchDTO);
        Page<StockHistoryDataVO> pageVr = new Page<StockHistoryDataVO>(page.getPageNo(), page.getPageSize());
        pageVr.setCount(page.getCount());

        if (page.getList() != null) {
            List<StockHistoryDataVO> list = new ArrayList<StockHistoryDataVO>();
            page.getList().forEach(item -> {
                StockHistoryDataVO vo = new StockHistoryDataVO();
                vo.setId(Integer.parseInt(item.get("id").toString()));
                vo.setName(String.valueOf(item.get("stockName")));
                vo.setCode(String.valueOf(item.get("stockCode")));
                vo.setClose(item.get("close") == null ? 0 : Double.parseDouble(item.get("close").toString()));
                vo.setRiseAndFall(item.get("riseAndFall") == null ? 0 : Double.parseDouble(item.get("riseAndFall").toString()));
                vo.setRiseAndFall(BigDecimal.valueOf(vo.getRiseAndFall()).setScale(2, RoundingMode.HALF_UP).doubleValue());
                vo.setLogo(stockLogoService.getLogoUrl(String.valueOf("stockCode"),
                        String.valueOf(item.get("logo")), String.valueOf(item.get("exchange"))));
                list.add(vo);
            });
            pageVr.setList(list);
        }
        return pageVr;
    }

    /**
     * 查询板块推荐股票 (侧栏下角显示)
     *
     * @param stockCode 股票代码
     * @return 查询结果
     */
    public List<Map<String, Object>> getStockAiRecommendStockList(String stockCode) {
        List<Map<String, Object>> list = stockDailyDao.getStockAiRecommendStockList(stockCode);
        List<Map<String, Object>> filterFields = new ArrayList<Map<String, Object>>();
        for (Map<String, Object> item : list) {
            // 重新构造map 是为了少返回字段给前端，提升速度
            Map<String, Object> nItem = new HashMap<String, Object>();
            nItem.put("stockCode", item.get("stockCode"));
            nItem.put("stockName", item.get("stockName"));
            nItem.put("riseAndFall", item.get("riseAndFall"));
            nItem.put("stockWeighted252dRS", item.get("stockWeighted252dRS"));
            nItem.put("stockStrongTrend", item.get("stockStrongTrend"));
            nItem.put("logo", stockLogoService.getLogoUrl(String.valueOf(nItem.get("stockCode")), String.valueOf(item.get("logo")),
                    String.valueOf(item.get("exchange"))));
            filterFields.add(nItem);
        }
        return filterFields;
    }
}
